package com.l.Thread.WaitNotify;

import java.util.ArrayList;
import java.util.List;

/**
 * 例子：有多个生产者和多个消费者，有一个存储的队列，当队列满的时候不能再生产，当队
 * 列空的时候不能售出
 *
 *
 * @author Mc.Chai
 * @program: Java基础
 * @create 2021-11-13-16:59 16:59
 */
public class TestProducerAndConsumer {
    public static void main(String[] args) {
        MyQueue myQueue=new MyQueue();
        Producer1 producer1=new Producer1(myQueue);
        Producer2 producer2=new Producer2(myQueue);
        Consumer consumer=new Consumer(myQueue);
        producer1.start();
        producer2.start();
        consumer.start();
    }
}
/**
 * 创建一个容量为4队列空间
 * */
class MyQueue{
    private List list=new ArrayList();
    private int size=4;
    //存入元素,整体加锁只允许一个线程同时进入
    public synchronized void offer(Object o){
        /**
         * 当list中满的时候进行，当前的线程进入等待
         * 判断解释：当第四次存入元素的时候，队列中只有3个元素，不进入判断，执行添加，所以判断语句取等号
         * 关于使用while循环和使用notifyAll()
         * */
        if (list.size()>=size){
            try {
                System.out.println(Thread.currentThread().getName()+"进行等待，存满需要释放");
                this.wait();                //进行等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.notifyAll();
        System.out.println(Thread.currentThread().getName()+"存入第"+ (list.size()+1) +"元素");
        list.add(o);
    }
    public synchronized Object poll(){
        /**
         * */
        while (list.size()==0){
            try {
                System.out.println(Thread.currentThread().getName()+"没有元素了，需要添加进行等待");
                this.wait();
                System.out.println("复活");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.notifyAll();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"拿出1个元素，还剩"+(list.size()-1)+"元素");
        return list.remove(0);//每次拿出队列的第一个元素
    }
}
/**
 * 生产者1
 * */
class Producer1 extends Thread{
    MyQueue myQueue;

    public Producer1(MyQueue myQueue) {
        this.myQueue = myQueue;
    }

    @Override
    public void run() {
        System.out.println("Producer开始");
        /**
         * 利用for循环进行存入元素
         * */
        for (char i = 'a'; i <='e'; i++) {          // a   b   c   d  e
            System.out.println(getName()+"准备进行赋值"+i);
            myQueue.offer(i);   //为队列添加元素
        }
        System.out.println("Producer结束");

    }
}
/**
 * 生产者2
 * */
class Producer2 extends Thread{
    MyQueue myQueue;

    public Producer2(MyQueue myQueue) {
        this.myQueue = myQueue;
    }

    @Override
    public void run() {
        System.out.println("Producer2开始");
        /**
         * 利用for循环进行存入元素
         * */
        for (char i = 'a'; i <='e'; i++) {          // a   b   c   d  e
            System.out.println(getName()+"准备进行赋值"+i);
            myQueue.offer(i);   //为队列添加元素
        }
        System.out.println("Producer2结束");

    }
}
/**
 * 消费者
 * */
class Consumer extends Thread{
    MyQueue myQueue;

    public Consumer(MyQueue myQueue) {
        this.myQueue = myQueue;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            myQueue.poll();
        }

    }
}